package edu.uc.labs.MobilePrinting.PrintUtils;

import edu.uc.labs.MobilePrinting.Configurator;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathExpressionException;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

/**
 * Writes or Gets a cache file based on printer settings
 * 
 * @param printer
 */
public class PrinterCache {

	private static Logger logger = Configurator.LOGGER;
	private static String cache_dir = Configurator.CACHEDIR;

	/*
	 * The name of the file to write is the name of the printer zone There will
	 * be one cache file per printer zone so when the user enters a new zone
	 * that printer will be the default printer installed, which is also the
	 * last printer in that zone that the user installed
	 */
	public static void writeCache(Printer p)
			throws ParserConfigurationException, IOException {
		TransformerFactory tFactory = null;
		Transformer transformer = null;
		try {
			tFactory = TransformerFactory.newInstance();
			transformer = tFactory.newTransformer();
		} catch (Exception e) {
			logger.debug(e.toString());
		}

		transformer.setOutputProperty("encoding", "UTF-8");

		DocumentBuilder builder;
		Document doc;
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		builder = factory.newDocumentBuilder();
		doc = builder.newDocument();

		doc.setXmlStandalone(true);

		Element root = doc.createElement("CONFIGURATIONS");
		Element e = doc.createElement("PRINTERS");
		Element e2 = doc.createElement("PRINTER");

		Text name = doc.createTextNode("" + p.getName());
		Element e3 = doc.createElement("NAME");
		e3.appendChild(name);

		Text server = doc.createTextNode("" + p.getServer());
		Element e4 = doc.createElement("SERVER");
		e4.appendChild(server);

		Text queue = doc.createTextNode("" + p.getQueue());
		Element e5 = doc.createElement("QUEUE");
		e5.appendChild(queue);

		Text driver = doc.createTextNode("" + p.getPPD());
		Element e6 = doc.createElement("DRIVER");
		e6.appendChild(driver);

		Text zone = doc.createTextNode("" + p.getZone());
		Element e7 = doc.createElement("ZONE");
		e7.appendChild(zone);

		Text location = doc.createTextNode("" + p.getLocation());
		Element e8 = doc.createElement("LOCATION");
		e8.appendChild(location);

		e2.appendChild(e3);
		e2.appendChild(e4);
		e2.appendChild(e5);
		e2.appendChild(e6);
		e2.appendChild(e7);
		e2.appendChild(e8);

		e.appendChild(e2);
		root.appendChild(e);
		doc.appendChild(root);

		ByteArrayOutputStream xmlBaos = new ByteArrayOutputStream();

		DOMSource source = new DOMSource(doc);
		try {
			transformer.transform(source, new StreamResult(xmlBaos));
		} catch (TransformerException e1) {
			e1.printStackTrace();
		}

		File f = new File(cache_dir + Configurator.CACHE + Configurator.DELIM
				+ p.getZone() + ".xml");
		FileWriter fstream = new FileWriter(f);
		BufferedWriter bOut = new BufferedWriter(fstream);
		bOut.write(xmlBaos.toString());
		bOut.close();
	}

	/**
	 * Read the cache file.
	 * 
	 * @param zone
	 *            - The zone that the computer is currently in
	 * @return the printer object that represents the last printer installed in
	 *         this zone
	 */
	public static Printer getCache(String zone) {
		ArrayList<Printer> printer = null;
		try {
			PrinterParser parser = new PrinterParser();
			printer = parser.parse(cache_dir + Configurator.CACHE
					+ Configurator.DELIM + zone + ".xml");
			logger.debug("trying to parse the file " + cache_dir
					+ Configurator.CACHE + Configurator.DELIM + zone + ".xml");
		} catch (SAXException ex) {
			// return new Printer();
			logger.debug(ex.toString());
		} catch (IOException ex) {
			// return new Printer();
			logger.debug(ex.toString());
		} catch (XPathExpressionException ex) {
			// return new Printer();
			logger.debug(ex.toString());
		} catch (ParserConfigurationException ex) {
			// return new Printer();
			logger.debug(ex.toString());
		} catch (IndexOutOfBoundsException ex) {
			logger.debug(ex.toString());
		}

		if (printer.isEmpty()) {
			logger.debug("The Printer array list is empty...");
			return new Printer();
		}
		return printer.get(0);
	}

}
